home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
COMM
/
TPASYNC
/
TPASYNC.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1990-01-23
|
11KB
|
340 lines
(*****************************************************************************
Turbo PASCAL Async Manager version 2.01
Copyright 1986-1990 by Kaleb Axon. All Rights Reserved.
For use with Turbo PASCAL 4.0
5.0
5.5
(Originally written in Turbo PASCAL 3.01)
The only requirement for freely incorporating this code into your own
programs is that the author of this code be given due credit wherever is
most appropriate (program's opening screen, copyright page or introduction
of manual, etc).
Information on updates and new releases to add to your library of Turbo
PASCAL source will be released from time to time via the PASCAL net-mail
echo, or you may drop me a note with your name and address (sent to the
address below).
If you have any questions or comments, please direct them to:
Kaleb Axon
1841 W. Katella St.
Springfield, MO 65807
*****************************************************************************)
{ update history: }
{ }
{ date programmer description of changes }
{ -------- --------------- ----------------------------------------------- }
{ 07/15/86 Kaleb Axon Initial writing }
{ 05/18/88 Kaleb Axon Now supports two ports simultaneously (1.10) }
{ 10/02/88 Kaleb Axon Converted to Turbo PASCAL 4.0 (2.00) }
{ 01/23/90 Kaleb Axon Increased maximum baud rate to 56000 bps (2.01) }
unit TPAsync;
interface
uses
Dos;
procedure AsyncCloseKeepDTR(Handle : byte);
function Carrier(Handle : byte) : boolean;
procedure AsyncSendString(Handle : byte;
S : string);
procedure AsyncSend(Handle : byte;
Ch : char);
function AsyncBufferCheck(Handle : byte) : boolean;
function AsyncBufferRead(Handle : byte;
var C : char) : boolean;
function AsyncOpen(Handle : byte;
ComPort : integer;
BaudRate : word;
Parity : char;
DataBits : integer;
StopBits : integer) : boolean;
procedure AsyncClose(Handle : byte);
procedure AsyncChange(Handle : byte;
BaudRate : word;
Parity : char;
DataBits : integer;
StopBits : integer);
implementation
const
UART : record
THR,RBR,IER,IIR,LCR,MCR,LSR,MSR : byte;
end =
(THR:$00;RBR:$00;IER:$01;IIR:$02;LCR:$03;MCR:$04;LSR:$05;
MSR:$06);
I8088 : record
IMR : byte;
end =
(IMR:$21);
type
AsyncBufferPointer = ^AsyncBufferType;
AsyncBufferType = array[0..4095] of char;
var
AsyncV : array[1..2] of record
HeapTop : ^integer;
Buffer : AsyncBufferPointer;
BufferHead : integer;
BufferTail : integer;
OpenFlag : boolean;
Port : byte;
Base : integer;
IRQ : integer;
BufferOverflow : boolean;
AsyncChar : char;
end;
AsyncBIOSPortTable : array[1..2] of integer absolute $0040:0000;
procedure AsyncChange(Handle : byte;
BaudRate : word;
Parity : char;
DataBits : integer;
StopBits : integer);
const
DivisorTable : array [1..10] of record
Baud : word;
Divisor : integer;
end =
((Baud:300; Divisor:384),
(Baud:450; Divisor:256),
(Baud:600; Divisor:192),
(Baud:1200; Divisor:96),
(Baud:2400; Divisor:48),
(Baud:4800; Divisor:24),
(Baud:9600; Divisor:12),
(Baud:19200; Divisor:6),
(Baud:38400; Divisor:3),
(Baud:56000; Divisor:2));
var
I : integer;
DV : integer;
LCR : integer;
begin
I := 0;
repeat
I := I+1;
until (DivisorTable[I].Baud = BaudRate) or (I > 10);
if I > 10 then
I := 1;
DV := DivisorTable[I].Divisor;
Parity := Upcase(Parity);
LCR := 0;
case Parity of
'E' : LCR := LCR or $18;
'O' : LCR := LCR or $08;
'N' : LCR := LCR or $00;
'M' : LCR := LCR or $28;
'S' : LCR := LCR or $38;
else
LCR := LCR or $00;
end;
case DataBits of
5 : LCR := LCR or $00;
6 : LCR := LCR or $01;
7 : LCR := LCR or $02;
8 : LCR := LCR or $03;
else
LCR := LCR or $03;
end;
if StopBits = 2 then
LCR := LCR or $04
else
LCR := LCR or $00;
LCR := LCR and $7F;
InLine($FA);
Port[UART.LCR+AsyncV[Handle ].Base] :=
Port[UART.LCR+AsyncV[Handle ].Base] or $80;
Port[AsyncV[Handle ].Base] := Lo(DV);
Port[AsyncV[Handle ].Base+1] := Hi(DV);
Port[UART.LCR+AsyncV[Handle ].Base] := LCR;
Inline($FB);
end;
procedure AsyncIsr1;
interrupt;
begin
if AsyncV[1].BufferHead-AsyncV[1].BufferTail < 4095 then
begin
Inc(AsyncV[1].BufferHead);
AsyncV[1].Buffer^[AsyncV[1].BufferHead mod 4096] :=
Chr(Port[UART.RBR+AsyncV[1].Base]);
Port[$20] := $20;
end else
begin
AsyncV[1].BufferOverflow := true;
AsyncV[1].AsyncChar := Chr(Port[UART.RBR+AsyncV[1].Base]);
Port[$20] := $20;
end;
end;
procedure AsyncIsr2;
begin
if AsyncV[2].BufferHead-AsyncV[2].BufferTail < 4095 then
begin
Inc(AsyncV[2].BufferHead);
AsyncV[2].Buffer^[AsyncV[2].BufferHead mod 4096] :=
Chr(Port[UART.RBR+AsyncV[2].Base]);
Port[$20] := $20;
end else
begin
AsyncV[2].BufferOverflow := true;
AsyncV[2].AsyncChar := Chr(Port[UART.RBR+AsyncV[2].Base]);
Port[$20] := $20;
end;
end;
function AsyncBufferRead(Handle : byte;
var C : char) : boolean;
begin
if AsyncV[Handle ].BufferHead < AsyncV[Handle ].BufferTail then
AsyncBufferRead := false
else
begin
C := AsyncV[Handle ].Buffer^[AsyncV[Handle ].BufferTail];
Inc(AsyncV[Handle ].BufferTail);
if AsyncV[Handle ].BufferTail = 4096then
begin
Dec(AsyncV[Handle ].BufferTail,4096);
Dec(AsyncV[Handle ].BufferHead,4096);
end;
AsyncBufferRead := true;
end;
end;
procedure AsyncClose(Handle : byte);
var
I,M : integer;
begin
if AsyncV[Handle ].OpenFlag then
begin
InLine($FA); { CLI }
I := Port[I8088.IMR];
M := 1 shl AsyncV[Handle ].IRQ;
Port[I8088.IMR] := I or M;
Port[UART.IER+AsyncV[Handle ].Base] := 0;
Port[UART.MCR+AsyncV[Handle ].Base] := 0;
InLine($FB); { STI }
Release(AsyncV[Handle ].HeapTop);
AsyncV[Handle ].OpenFlag := false;
end;
end;
function AsyncOpen(Handle : byte;
ComPort : integer;
BaudRate : word;
Parity : char;
DataBits : integer;
StopBits : integer) : boolean;
var
ComParm : integer;
I,M : integer;
Ch : char;
begin
if AsyncV[Handle ].OpenFlag then
AsyncClose(Handle );
Mark(AsyncV[Handle ].HeapTop);
New(AsyncV[Handle ].Buffer);
if (ComPort = 2) and (AsyncBIOSPortTable[2] <> 0) then
AsyncV[Handle ].Port := 2
else
AsyncV[Handle ].Port := 1;
AsyncV[Handle ].Base := AsyncBIOSPortTable[AsyncV[Handle ].Port];
AsyncV[Handle ].IRQ := Hi(AsyncV[Handle ].Base)+1;
if (Port[UART.IIR+AsyncV[Handle ].Base] and $00F8) <> 0 then
AsyncOpen := false
else
begin
AsyncV[Handle ].BufferHead := 0;
AsyncV[Handle ].BufferTail := 1;
AsyncV[Handle ].BufferOverflow := false;
AsyncChange(Handle ,BaudRate,Parity,DataBits,StopBits);
if Handle = 1 then
SetIntVec((AsyncV[Handle ].IRQ+8) and $00FF,@AsyncIsr1)
else
SetIntVec((AsyncV[Handle ].IRQ+8) and $00FF,@AsyncIsr1);
Inline($FA); { CLI }
Port[UART.LCR+AsyncV[Handle ].Base] := Port[UART.LCR+AsyncV[Handle ].Base] and $7F;
I := Port[UART.LSR+AsyncV[Handle ].Base];
I := Port[UART.RBR+AsyncV[Handle ].Base];
I := Port[I8088.IMR];
M := (1 shl AsyncV[Handle ].IRQ) xor $00FF;
Port[I8088.IMR] := I and M;
Port[UART.IER+AsyncV[Handle ].Base] := $01;
I := Port[UART.MCR+AsyncV[Handle ].Base];
Port[UART.MCR+AsyncV[Handle ].Base] := I or $08;
Inline($FB); { CLI }
AsyncV[Handle ].OpenFlag := true;
AsyncOpen := true;
end;
end;
function AsyncBufferCheck(Handle : byte) : boolean;
begin
AsyncBufferCheck := (AsyncV[Handle ].BufferHead >= AsyncV[Handle ].BufferTail);
end;
procedure AsyncSend(Handle : byte;
Ch : char);
var
I,M,C : integer;
begin
Port[UART.MCR+AsyncV[Handle ].Base] := $0B;
C := MaxInt;
while (C <> 0) and ((Port[UART.LSR+AsyncV[Handle ].Base] and $20) = 0) do
C := C-1;
if C <> 0 then
begin
InLine($FA);
Port[UART.THR+AsyncV[Handle ].Base] := Ord(Ch);
InLine($FB);
end else
WriteLn('<<<TIMEOUT>>>');
end;
procedure AsyncSendString(Handle : byte;
S : string);
var
I : integer;
begin
for I := 1 to Length(S) do
AsyncSend(Handle ,S[I]);
end;
function Carrier(Handle : byte) : boolean;
begin
if (Port[UART.MSR+AsyncV[Handle ].Base] and $80) <> 0 then
Carrier := true
else
Carrier := false;
end;
procedure AsyncCloseKeepDTR(Handle : byte);
var
I,M : integer;
begin
if AsyncV[Handle ].OpenFlag then
begin
InLine($FA);
I := Port[I8088.IMR];
M := 1 shl AsyncV[Handle ].IRQ;
Port[I8088.IMR] := I or M;
Port[UART.IER+AsyncV[Handle ].Base] := 0;
Port[UART.MCR+AsyncV[Handle ].Base] := 1;
InLine($FB);
AsyncV[Handle ].OpenFlag := false;
end;
end;
begin
AsyncV[1].OpenFlag := false;
AsyncV[2].OpenFlag := false;
end.